Skip to content

feat(core): Add longTaskIntegration to report JS long tasks as metrics - #6986

Merged
alwx merged 5 commits into
mainfrom
alwx/feature/6185
Nov 5, 2026
Merged

alwx merged 5 commits into
mainfrom
alwx/feature/6185

Conversation

@alwx

@alwx alwx commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

📢 Type of change

  • Bugfix
  • New feature
  • Enhancement
  • Refactoring

📜 Description

Adds the opt-in longTaskIntegration. It listens to the React Native PerformanceObserver for longtask entries and sends each task of at least minDurationMs (default 200 ms) as the react_native.long_task.duration distribution metric, without an active transaction. sampleRate (default 1) is checked once per app launch, and the integration does nothing where long tasks are not supported (Old Architecture, React Native below 0.82).

💡 Motivation and Context

Stall tracking only records JS thread blocking inside a transaction, so customers cannot see blocking across their fleet. Metrics carry the scope attributes and user from @sentry/core, so apps can filter by their own attributes. Closes #6185.

💚 How did you test it?

Unit tests with a fake PerformanceObserver cover the threshold, sampling, unsupported environments, observe() errors, and disconnect on client close. I have not run it on a device yet.

📝 Checklist

  • I added tests to verify changes.
  • No new PII added or SDK only sends newly added PII if sendDefaultPII is enabled.
  • I updated the docs if needed.
  • I updated the wizard if needed.
  • All tests passing.
  • Public API changes reviewed by another Mobile SDK team member or implemented according to the develop docs spec.
  • No breaking changes.

🔮 Next steps

Verify the metric in a sample app on React Native 0.82+ with the New Architecture, and document the integration on docs.sentry.io.

@github-actions

github-actions Bot commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

Semver Impact of This PR

⚪ None (no version bump detected)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


  • feat(core): Add longTaskIntegration to report JS long tasks as metrics by alwx and markushi in #6986
  • feat(ios): Report JS thread hangs as errors (iOS only) by alwx in #6964
  • chore(deps): update Cocoa SDK to v9.33.0 by github-actions in #6987
  • feat(profiling): Send Hermes samples as UI profile chunks on Android by alwx in #6966
  • fix(tracing): Detect expo/fetch behind the Expo Router fetch wrapper by antonis and claude in #6965
  • ci(release): Bump craft to 3.9.0 and update config by BYK with sentry-junior in #6984
  • docs(core): Drop stale logger.warn note from AGENTS.md by antonis and claude in #6968
  • chore(deps): update JavaScript SDK to v10.78.0 by antonis and claude in #6973
  • chore(deps): Bump getsentry/craft from 2.35.0 to 3.5.0 by alwx in #6983
  • chore(deps): update Maestro to v2.12.1 by github-actions in #6981
  • chore(deps): bump getsentry/craft/.github/workflows/changelog-preview.yml from 3.0.0 to 3.4.1 by alwx with dependabot in #6979
  • chore(deps): bump node-forge from 1.4.0 to 1.4.2 by dependabot in #6982
  • chore(deps): bump getsentry/github-workflows/validate-pr from 36c729264d2edc29ebae61950c50e1e9f043ad7e to 01bcb7fe69bb48bacd83e675840e3dc95b33c730 by dependabot in #6978
  • chore(deps): bump ruby/setup-ruby from 1.334.0 to 1.336.0 by dependabot in #6977
  • chore(deps): bump gradle/actions/setup-gradle from 6.4.0 to 6.4.1 by dependabot in #6976
  • fix(ios): Honor Sentry.Mask in error screenshots by antonis and claude in #6974
  • fix(android): Restore enableLogs option mapping by antonis and claude in #6967
  • chore(deps): update Wizard to v9.1.0 by github-actions in #6972
  • chore(deps): update Sentry Android Gradle Plugin to v6.25.0 by github-actions in #6971

🤖 This preview updates automatically when you update the PR.

@github-actions

github-actions Bot commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor
Messages
📖 Do not forget to update Sentry-docs with your feature once the pull request gets approved.

Generated by 🚫 dangerJS against d0b151e

alwx added a commit that referenced this pull request Nov 4, 2026
Replace the #XXXX placeholder in the CHANGELOG entry with the number of
the pull request, #6986, now that the PR exists.
@alwx
alwx marked this pull request as ready for review November 4, 2026 10:50
@alwx
alwx requested review from a team and lucas-zimerman as code owners November 4, 2026 10:50
@alwx
alwx requested review from NinjaLikesCheez, antonis, buenaflor, markushi, philprime and runningcode and removed request for a team November 4, 2026 10:50
@alwx alwx added the ready-to-merge Triggers the full CI test suite label Nov 4, 2026
@sentry

sentry Bot commented Nov 4, 2026 •

Copy link
Copy Markdown

📲 Install Builds

Android

🔗 App Name App ID Version Configuration
Sentry RN io.sentry.reactnative.sample 8.33.0 (113) Release

⚙️ sentry-react-native Build Distribution Settings

@antonis antonis left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left a couple of comments but overall the code changes LGTM 🚀

🔮 Next steps

Verify the metric in a sample app on React Native 0.82+ with the New Architecture, and document the integration on docs.sentry.io.

Let's do that now so that we can test e2e before shipping this and add a link in the description.

return;
}

if (Math.random() >= sampleRate) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

q: Why a sample rate for this metric when metrics by default doesnt have a sample rate?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The issue (#6185) asks for a configurable sample rate. The customer wants this across a large fleet, and the option lets them cut volume and the on-device work. The SDK decides once per launch, so a sampled launch reports all its long tasks, and filtering by user still shows a full picture. The JSDoc says that Sentry does not scale the counts by this rate. Users can also drop metrics in beforeSendMetric, so I can remove the option if we prefer fewer knobs.

return;
}

if (Math.random() >= sampleRate) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

q: would there be any benefit in using import { _INTERNAL_safeMathRandom } from '@sentry/core'; here?

@alwx alwx Nov 5, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked it, and it gives no benefit here. _INTERNAL_safeMathRandom only wraps Math.random() when a framework sets the __SENTRY_SAFE_RANDOM_ID_WRAPPER__ global, which is for server prerendering, for example in Next.js. React Native never sets it so the call is plain Math.random(). The profiling integration in this SDK also uses Math.random() for sampling.

alwx added 3 commits November 5, 2026 11:24
Stall tracking only records JS thread blocking inside an active
transaction, so blocking outside of traced work stays invisible.

The new opt-in longTaskIntegration listens to the React Native
PerformanceObserver for 'longtask' entries and sends each task of at
least minDurationMs (default 200 ms) as the
react_native.long_task.duration distribution metric. It does not
depend on tracing. Scope attributes and the user come from the metrics
pipeline in @sentry/core, so apps can filter by their own attributes.

sampleRate (default 1) is checked once per launch, so a sampled launch
reports all its long tasks. The observer uses buffered: true to also
report tasks from before Sentry.init, and disconnects when the client
closes.

React Native installs PerformanceObserver with 'longtask' support only
from 0.82 on the New Architecture, and fixes the native threshold at
50 ms. In other environments the integration logs a debug message and
does nothing.
Replace the #XXXX placeholder in the CHANGELOG entry with the number of
the pull request, #6986, now that the PR exists.
…ection

longTaskIntegration now returns early when enableMetrics is false.
@sentry/core already drops the metrics in that case, but the observer
still ran on the device for nothing.

The support check now runs inside the try/catch. Reading the lazy
PerformanceObserver global loads the React Native module, and
supportedEntryTypes calls into native code, so both can throw. An error
there now logs a debug warning instead of breaking client setup.
@alwx
alwx force-pushed the alwx/feature/6185 branch from 52776ac to d30d70a Compare November 5, 2026 10:26

@antonis antonis left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

Tested with a follow up sample PR #6989 and worked as expected.

@markushi markushi left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Left 2 tiny nits.

alwx and others added 2 commits November 5, 2026 13:04
Co-authored-by: Markus Hintersteiner <markus.hintersteiner@sentry.io>
Co-authored-by: Markus Hintersteiner <markus.hintersteiner@sentry.io>
@alwx
alwx enabled auto-merge (squash) November 5, 2026 12:05
@alwx
alwx merged commit c39e39c into main Nov 5, 2026
39 of 76 checks passed
@alwx
alwx deleted the alwx/feature/6185 branch November 5, 2026 12:07
antonis added a commit that referenced this pull request Nov 5, 2026
* feat(core): Add longTaskIntegration to report JS long tasks as metrics

Stall tracking only records JS thread blocking inside an active
transaction, so blocking outside of traced work stays invisible.

The new opt-in longTaskIntegration listens to the React Native
PerformanceObserver for 'longtask' entries and sends each task of at
least minDurationMs (default 200 ms) as the
react_native.long_task.duration distribution metric. It does not
depend on tracing. Scope attributes and the user come from the metrics
pipeline in @sentry/core, so apps can filter by their own attributes.

sampleRate (default 1) is checked once per launch, so a sampled launch
reports all its long tasks. The observer uses buffered: true to also
report tasks from before Sentry.init, and disconnects when the client
closes.

React Native installs PerformanceObserver with 'longtask' support only
from 0.82 on the New Architecture, and fixes the native threshold at
50 ms. In other environments the integration logs a debug message and
does nothing.

* docs(core): Link longTaskIntegration changelog entry to its PR

Replace the #XXXX placeholder in the CHANGELOG entry with the number of
the pull request, #6986, now that the PR exists.

* fix(core): Skip long task observer when metrics are off and guard detection

longTaskIntegration now returns early when enableMetrics is false.
@sentry/core already drops the metrics in that case, but the observer
still ran on the device for nothing.

The support check now runs inside the try/catch. Reading the lazy
PerformanceObserver global loads the React Native module, and
supportedEntryTypes calls into native code, so both can throw. An error
there now logs a debug warning instead of breaking client setup.

* chore: Add longTaskIntegration to the React Native sample

Enable longTaskIntegration with a 100 ms threshold and add a button on
the Performance screen that blocks the JS thread for 300 ms, so the
react_native.long_task.duration metric can be tested end to end.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Alexander Pantiukhov <alex@apantiukhov.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-to-merge Triggers the full CI test suite

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add standalone long task detection integration

4 participants